package com.jarveis.frame.util;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;

import com.jarveis.frame.lang.CharacterUtil;
import com.jarveis.frame.lang.StringUtil;

/**
 * 分词工具类
 * 
 * @author liuguojun
 */
public class WordSeg {

	private static final Logger logger = Logger.getLogger(WordSeg.class);

	private static File dicFile = null;
	private static long lastModified = 0L;

	private static Set<String> DIC = new HashSet<String>();
	private static int MAX_LENGTH;

	/**
	 * 加载字典
	 * 
	 * @param dicPath
	 */
	public static void reload(String dicPath) {
		if (null == dicFile) {
			dicFile = new File(dicPath);
		}
		
		if (dicFile.lastModified() > lastModified) {
			synchronized (WordSeg.class) {
				int max = 1;
				lastModified = dicFile.lastModified();
				List lines = new ArrayList();
				try {
					lines = FileUtils.readLines(dicFile, CharacterUtil.UTF8);
				} catch (IOException ex) {
					logger.error("读取字典出错", ex);
				}

				String lineStr = "";
				for (Object line : lines) {
					lineStr = (String) line;
					if (StringUtil.isBlank(lineStr)) {
						continue;
					}

					DIC.add(lineStr);
					if (lineStr.length() > max) {
						max = lineStr.length();
					}
				}
				MAX_LENGTH = max;
			}
		}
	}

	/**
	 * 分割词语
	 * 
	 * @param text
	 * @param ignore
	 * @return
	 */
	public static Map<String, Integer> seg(String text, boolean ignore) {
		Map<String, Integer> map = new LinkedHashMap<String, Integer>();
		while (text.length() > 0) {
			int len = MAX_LENGTH;
			if (text.length() < len) {
				len = text.length();
			}
			
			boolean isSingle = false;
			// 取指定的最大长度的文本去词典里面匹配
			String tryWord = text.substring(0, 0 + len);
			while (!DIC.contains(tryWord)) {
				// 如果长度为一且在词典中未找到匹配，则按长度为一切分
				if (tryWord.length() == 1) {
					isSingle = true;
					break;
				}
				// 如果匹配不到，则长度减一继续匹配
				tryWord = tryWord.substring(0, tryWord.length() - 1);
			}

			if (ignore && isSingle) {
				logger.info("ignore word : " + tryWord);
			} else {
				Integer count = map.get(tryWord);
				if (count == null) {
					map.put(tryWord, 1);
				} else {
					map.put(tryWord, count + 1);
				}
			}

			// 从待分词文本中去除已经分词的文本
			text = text.substring(tryWord.length());
		}

		return map;
	}

	/**
	 * 添加关键字
	 * 
	 * @param word
	 */
	public static void add(String word) {
		word = word.toLowerCase();
		if (!DIC.contains(word)) {
			DIC.add(word);
			try {
				FileUtils.writeLines(dicFile, CharacterUtil.UTF8, DIC);
			} catch (IOException ex) {
				logger.error("写入分词字典出错", ex);
			}
			lastModified = dicFile.lastModified();
		}
	}

	/**
	 * 删除关键字
	 * 
	 * @param word
	 */
	public static void remove(String word) {
		if (DIC.contains(word)) {
			DIC.remove(word);
			try {
				FileUtils.writeLines(dicFile, CharacterUtil.UTF8, DIC);
			} catch (IOException ex) {
				logger.error("写入分词字典出错", ex);
			}
			lastModified = dicFile.lastModified();
		}
	}
}
